source('../settings/settings.R')
source('commonFunctions.R')
set.seed(43)
drive1 <- read.csv('../data/processed/analysis/TT1_Drive_1_PP.csv')
drive2 <- read.csv('../data/processed/Analysis/TT1_Drive_2_PP.csv')
drive3 <- read.csv('../data/processed/Analysis/TT1_Drive_3_PP.csv')
drive4 <- read.csv('../data/processed/Analysis/TT1_Drive_4_PP.csv', stringsAsFactors = T)
dfSeg <- data.frame(rep(1, nrow(drive4)), rep(2, nrow(drive4)), rep(3, nrow(drive4)), rep(4, nrow(drive4)))
names(dfSeg) <- c("Seg1", "Seg2", "Seg3", "Seg4")

combinedDf_Seg1 <- cbind(drive4, 
                    drive1$MeanPP_Seg0, 
                    drive2$MeanPP_Seg1, drive3$MeanPP_Seg1, 
                    drive2$MeanPP_Seg0, drive3$MeanPP_Seg0,
                    drive2$StdPP, drive3$StdPP,
                    dfSeg$Seg1
                  )
combinedDf_Seg2 <- cbind(drive4, 
                    drive1$MeanPP_Seg0, 
                    drive2$MeanPP_Seg2, drive3$MeanPP_Seg2, 
                    drive2$MeanPP_Seg0, drive3$MeanPP_Seg0,
                    drive2$StdPP, drive3$StdPP,
                    dfSeg$Seg2
                  )
combinedDf_Seg3 <- cbind(drive4, 
                    drive1$MeanPP_Seg0, 
                    drive2$MeanPP_Seg3, drive3$MeanPP_Seg3, 
                    drive2$MeanPP_Seg0, drive3$MeanPP_Seg0,
                    drive2$StdPP, drive3$StdPP,
                    dfSeg$Seg3
                  )
combinedDf_Seg4 <- cbind(drive4, 
                    drive1$MeanPP_Seg0, 
                    drive2$MeanPP_Seg4, drive3$MeanPP_Seg4, 
                    drive2$MeanPP_Seg0, drive3$MeanPP_Seg0,
                    drive2$StdPP, drive3$StdPP,
                    dfSeg$Seg4
                  )

names(combinedDf_Seg1) <- c(names(drive4), 
                       "PP_Dev_1_Turning",
                       "PP_Dev_2_Straight", "PP_Dev_3_Straight", 
                       "PP_Dev_2_Turning", "PP_Dev_3_Turning", 
                       "Std_PP_2", "Std_PP_3", "Segment")
names(combinedDf_Seg2) <- c(names(drive4), 
                       "PP_Dev_1_Turning",
                       "PP_Dev_2_Straight", "PP_Dev_3_Straight", 
                       "PP_Dev_2_Turning", "PP_Dev_3_Turning", 
                       "Std_PP_2", "Std_PP_3", "Segment")
names(combinedDf_Seg3) <- c(names(drive4), 
                       "PP_Dev_1_Turning",
                       "PP_Dev_2_Straight", "PP_Dev_3_Straight", 
                       "PP_Dev_2_Turning", "PP_Dev_3_Turning", 
                       "Std_PP_2", "Std_PP_3", "Segment")
names(combinedDf_Seg4) <- c(names(drive4), 
                       "PP_Dev_1_Turning",
                       "PP_Dev_2_Straight", "PP_Dev_3_Straight", 
                       "PP_Dev_2_Turning", "PP_Dev_3_Turning", 
                       "Std_PP_2", "Std_PP_3", "Segment")

combinedDf_Seg1$Subject <- paste0(as.factor(combinedDf_Seg1$Subject), ".S1")
combinedDf_Seg2$Subject <- paste0(as.factor(combinedDf_Seg2$Subject), ".S2")
combinedDf_Seg3$Subject <- paste0(as.factor(combinedDf_Seg3$Subject), ".S3")
combinedDf_Seg4$Subject <- paste0(as.factor(combinedDf_Seg4$Subject), ".S4")

combinedDf <- rbind(combinedDf_Seg1, combinedDf_Seg2, combinedDf_Seg3, combinedDf_Seg4)

combinedDf$Subject <- paste0("#", str_pad(combinedDf$Subject, 2, pad="0"))
combinedDf$Segment <- as.factor(combinedDf$Segment)
combinedDf_NoStressor <- combinedDf[combinedDf$Activity == "NO",]
combinedDf_Cognitive <- combinedDf[combinedDf$Activity == "C",]
combinedDf_Motoric <- combinedDf[combinedDf$Activity == "M",]

# combinedDf_NoStressor$Subject <- as.factor(combinedDf_NoStressor$Subject)
# combinedDf_Cognitive$Subject <- as.factor(combinedDf_Cognitive$Subject)
# combinedDf_Motoric$Subject <- as.factor(combinedDf_Motoric$Subject)
COLOR_NORMAL <- list(color='rgb(120,120,120)')
COLOR_COGNITIVE <- list(color='rgb(158,202,225)')
COLOR_MOTORIC <- list(color='rgb(58,200,225)')
COLOR_FAILURE <- list(color='red')

THRESHOLD_MILD = 0.07
THRESHOLD_EXTREME = 0.2

MARKER_LINE_MILD = list(color="blue")
MARKER_LINE_EXTREME = list(color="red")
yAxis <- list(title = 'Perinasal Perspiration (Log)', range=c(-0.3, 0.5))

fig_NoStressor <- plot_ly(combinedDf_NoStressor, x = ~Subject, y = ~PP_Dev_2_Straight, type = 'bar', name = 'Cognitive - Mean PP (Straight)', marker=COLOR_COGNITIVE) %>%
  add_trace(y = ~PP_Dev_3_Straight, name = 'Motoric - Mean PP (Straight)', marker=COLOR_MOTORIC) %>% 
  add_trace(y = ~PP_Dev_2_Turning, name = 'Cognitive - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>% 
  add_trace(y = ~PP_Dev_3_Turning, name = 'Motoric - Mean PP (Turning)', marker=COLOR_MOTORIC) %>% 
  add_trace(y = ~PP_Dev, name = 'Failure - PP Deviation', marker=COLOR_FAILURE) %>% 
  add_segments(x="#1.S1", xend="#7.S4", y = THRESHOLD_MILD, yend = THRESHOLD_MILD, name="Threshold: Mild Change of PP",
                           line=list(color="blue", dash = 'dot')) %>%
  # add_segments(x="#01", xend="#41", y = THRESHOLD_EXTREME, yend = THRESHOLD_EXTREME, name="Threshold: Extreme Change of PP",
  #                          line=list(color="darkred", dash = 'dot')) %>%
  layout(yaxis = yAxis, barmode = 'group', title="Failure Driving \n Group=No Stressor")

htmltools::tagList(fig_NoStressor)
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
yAxis <- list(title = 'Perinasal Perspiration (Log)', range=c(-0.3, 0.3))

fig_Cognitive <- plot_ly(combinedDf_Cognitive, x = ~Subject, y = ~PP_Dev_2_Straight, type = 'bar', name = 'Cognitive - Mean PP (Straight)', marker=COLOR_COGNITIVE) %>%
  add_trace(y = ~PP_Dev_3_Straight, name = 'Motoric - Mean PP (Straight)', marker=COLOR_MOTORIC) %>% 
  add_trace(y = ~PP_Dev_2_Turning, name = 'Cognitive - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>% 
  add_trace(y = ~PP_Dev_3_Turning, name = 'Motoric - Mean PP (Turning)', marker=COLOR_MOTORIC) %>% 
  add_trace(y = ~PP_Dev, name = 'Failure - PP Deviation', marker=COLOR_FAILURE) %>% 
  add_segments(x="#12.S1", xend="#3.S4", y = THRESHOLD_MILD, yend = THRESHOLD_MILD, name="Threshold: Mild Change of PP",
                           line=list(color="blue", dash = 'dot')) %>%
  # add_segments(x="#02", xend="#22", y = THRESHOLD_EXTREME, yend = THRESHOLD_EXTREME, name="Threshold: Extreme Change of PP",
  #                          line=list(color="darkred", dash = 'dot')) %>%
  layout(yaxis = yAxis, barmode = 'group', title="Failure Driving \n Group=Cognitive")

htmltools::tagList(fig_Cognitive)
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
yAxis <- list(title = 'Perinasal Perspiration (Log)', range=c(-0.3, 0.5))

fig_Motoric <- plot_ly(combinedDf_Motoric, x = ~Subject, y = ~PP_Dev_2_Straight, type = 'bar', name = 'Cognitive - Mean PP (Straight)', marker=COLOR_COGNITIVE) %>%
  add_trace(y = ~PP_Dev_3_Straight, name = 'Motoric - Mean PP (Straight)', marker=COLOR_MOTORIC) %>% 
  add_trace(y = ~PP_Dev_2_Turning, name = 'Cognitive - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>% 
  add_trace(y = ~PP_Dev_3_Turning, name = 'Motoric - Mean PP (Turning)', marker=COLOR_MOTORIC) %>% 
  add_trace(y = ~PP_Dev, name = 'Failure - PP Deviation', marker=COLOR_FAILURE) %>% 
  add_segments(x="#24.S1", xend="#9.S4", y = THRESHOLD_MILD, yend = THRESHOLD_MILD, name="Threshold: Mild Change of PP",
                           line=list(color="blue", dash = 'dot')) %>%
  # add_segments(x="#05", xend="#31", y = THRESHOLD_EXTREME, yend = THRESHOLD_EXTREME, name="Threshold: Extreme Change of PP",
  #                          line=list(color="darkred", dash = 'dot')) %>%
  layout(yaxis = yAxis, barmode = 'group', title="Failure Driving \n Group: Motoric")

htmltools::tagList(fig_Motoric)
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
library(nlme)
combinedDf$Subject = as.factor(combinedDf$Subject)
combinedDf$Activity = as.factor(combinedDf$Activity)
combinedDf$PP_Dev_Group = ifelse(combinedDf$PP_Dev > THRESHOLD_MILD, 1, 0)
model = lme(PP_Dev ~ 
              abs(PP_Dev_2_Straight)
              + abs(PP_Dev_3_Straight)
              + abs(PP_Dev_2_Turning) 
              + abs(PP_Dev_3_Turning)
              + factor(Activity), 
            random=~1|Subject,
            data=combinedDf,
            method="REML")

# anova(model)
summary(model)
Linear mixed-effects model fit by REML
 Data: combinedDf 

Random effects:
 Formula: ~1 | Subject
        (Intercept)   Residual
StdDev:  0.06061321 0.02272995

Fixed effects: PP_Dev ~ abs(PP_Dev_2_Straight) + abs(PP_Dev_3_Straight) + abs(PP_Dev_2_Turning) +      abs(PP_Dev_3_Turning) + factor(Activity) 
 Correlation: 
                       (Intr) a(PP_D_2_S a(PP_D_3_S a(PP_D_2_T a(PP_D_3_T fc(A)M
abs(PP_Dev_2_Straight)  0.212                                                   
abs(PP_Dev_3_Straight) -0.017 -0.131                                            
abs(PP_Dev_2_Turning)  -0.142 -0.560     -0.333                                 
abs(PP_Dev_3_Turning)  -0.532 -0.125     -0.499     -0.012                      
factor(Activity)M      -0.498 -0.117      0.040     -0.167      0.151           
factor(Activity)NO     -0.356 -0.101      0.300     -0.292     -0.100      0.532

Standardized Within-Group Residuals:
        Min          Q1         Med          Q3         Max 
-0.55213368 -0.36118802  0.01449327  0.22338495  0.72942632 

Number of Observations: 84
Number of Groups: 84 
plot(model)

model = lme(PP_Dev ~ 
              abs(PP_Dev_2_Turning)
              + factor(Activity), 
            random=~1|Subject,
            data=combinedDf,
            method="REML")

# anova(model)
summary(model)
Linear mixed-effects model fit by REML
 Data: combinedDf 

Random effects:
 Formula: ~1 | Subject
        (Intercept)   Residual
StdDev:  0.06060021 0.02272508

Fixed effects: PP_Dev ~ abs(PP_Dev_2_Turning) + factor(Activity) 
 Correlation: 
                      (Intr) a(PP_D fc(A)M
abs(PP_Dev_2_Turning) -0.460              
factor(Activity)M     -0.486 -0.261       
factor(Activity)NO    -0.421 -0.358  0.544

Standardized Within-Group Residuals:
        Min          Q1         Med          Q3         Max 
-0.50898879 -0.36206730  0.01408431  0.24267504  0.66132090 

Number of Observations: 84
Number of Groups: 84 
plot(model)

model = lme(PP_Dev ~ 
              PP_Dev_2_Straight + 
              PP_Dev_3_Straight + 
              PP_Dev_1_Turning + 
              PP_Dev_2_Turning + 
              PP_Dev_3_Turning + 
              Std_PP_2 + 
              Std_PP_3 +
              factor(Activity), 
            random=~1|Subject,
            data=combinedDf,
            method="REML")

# anova(model)
summary(model)
Linear mixed-effects model fit by REML
 Data: combinedDf 

Random effects:
 Formula: ~1 | Subject
        (Intercept)   Residual
StdDev:  0.06098518 0.02286952

Fixed effects: PP_Dev ~ PP_Dev_2_Straight + PP_Dev_3_Straight + PP_Dev_1_Turning +      PP_Dev_2_Turning + PP_Dev_3_Turning + Std_PP_2 + Std_PP_3 +      factor(Activity) 
 Correlation: 
                   (Intr) PP_D_2_S PP_D_3_S PP_D_1 PP_D_2_T PP_D_3_T S_PP_2 S_PP_3 fc(A)M
PP_Dev_2_Straight  -0.204                                                                
PP_Dev_3_Straight  -0.058 -0.186                                                         
PP_Dev_1_Turning   -0.874  0.318    0.192                                                
PP_Dev_2_Turning    0.609 -0.751   -0.024   -0.646                                       
PP_Dev_3_Turning   -0.175  0.190   -0.662   -0.099 -0.319                                
Std_PP_2            0.458 -0.306   -0.149   -0.507  0.669   -0.282                       
Std_PP_3           -0.880  0.361    0.132    0.810 -0.781    0.192   -0.742              
factor(Activity)M  -0.095 -0.093    0.321    0.125 -0.021   -0.214    0.016 -0.079       
factor(Activity)NO -0.445 -0.027    0.278    0.344 -0.287   -0.072   -0.360  0.411  0.440

Standardized Within-Group Residuals:
          Min            Q1           Med            Q3           Max 
-0.6289604009 -0.2872063327  0.0004924481  0.2889330700  0.6496413406 

Number of Observations: 84
Number of Groups: 84 
plot(model)

Machine Learning

combinedDf$PP_Dev <- NULL

combinedDf$Subject <- NULL
combinedDf$Activity_NO <- ifelse(combinedDf$Activity == "NO", 1, 0)
combinedDf$Activity_C <- ifelse(combinedDf$Activity == "C", 1, 0)
combinedDf$Activity_M <- ifelse(combinedDf$Activity == "M", 1, 0)
combinedDf$Activity <- NULL

combinedDf$InSegment1 <- ifelse(combinedDf$Segment == 1, 1, 0)
combinedDf$InSegment2 <- ifelse(combinedDf$Segment == 2, 1, 0)
combinedDf$InSegment3 <- ifelse(combinedDf$Segment == 3, 1, 0)
combinedDf$InSegment4 <- ifelse(combinedDf$Segment == 4, 1, 0)
combinedDf$Segment <- NULL

combinedDf$Class <- ifelse(combinedDf$PP_Dev_Group == 1, T, F)
combinedDf$PP_Dev_Group <- NULL
# library(mefa)
# combinedDf <- rep(combinedDf, 10) 
n_folds <- 10
params <- param <- list(objective   = "binary:logistic", 
               booster          = "gbtree",
               eval_metric      = "auc",
               eta              = 0.1,
               max_depth        = 8,
               alpha            = 1,
               lambda           = 0,
               gamma            = 0.3,
               min_child_weight = 0.3,
               subsample        = 1,
               colsample_bytree = 0.5)
           
# XGBoost Model     
ml_data <- as.matrix(combinedDf %>% select(-Class))

xgb_m <- xgb.cv(   params               = param,
                  data = ml_data ,
                  label =  combinedDf$Class,
                  nrounds             = 500,
                  verbose             = F,
                  prediction          = T,
                  maximize            = T,
                  nfold               = n_folds,
                  metrics             = c("auc", "error"),
                  early_stopping_rounds = 100,
                  scale_pos_weight      = 3.05)

# xgb_m$evaluation_log[xgb_m$best_iteration,"test_auc_mean"]
xgb_m$evaluation_log[xgb_m$best_iteration,]
NA
library(pROC)

# it = which.max(xgb_m$evaluation_log$test_auc_mean)
# best.iter = xgb_m$evaluation_log$iter[it]
# best.iter 

plot(pROC::roc(response = ifelse(combinedDf$Class==T, 1, 0),
               predictor = xgb_m$pred,
               levels=c(0, 1)),
     lwd=1.5) 
Setting direction: controls < cases

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CnNvdXJjZSgnLi4vc2V0dGluZ3Mvc2V0dGluZ3MuUicpCnNvdXJjZSgnY29tbW9uRnVuY3Rpb25zLlInKQpgYGAKCmBgYHtyfQpzZXQuc2VlZCg0MykKZHJpdmUxIDwtIHJlYWQuY3N2KCcuLi9kYXRhL3Byb2Nlc3NlZC9hbmFseXNpcy9UVDFfRHJpdmVfMV9QUC5jc3YnKQpkcml2ZTIgPC0gcmVhZC5jc3YoJy4uL2RhdGEvcHJvY2Vzc2VkL0FuYWx5c2lzL1RUMV9Ecml2ZV8yX1BQLmNzdicpCmRyaXZlMyA8LSByZWFkLmNzdignLi4vZGF0YS9wcm9jZXNzZWQvQW5hbHlzaXMvVFQxX0RyaXZlXzNfUFAuY3N2JykKZHJpdmU0IDwtIHJlYWQuY3N2KCcuLi9kYXRhL3Byb2Nlc3NlZC9BbmFseXNpcy9UVDFfRHJpdmVfNF9QUC5jc3YnLCBzdHJpbmdzQXNGYWN0b3JzID0gVCkKYGBgCgpgYGB7cn0KZGZTZWcgPC0gZGF0YS5mcmFtZShyZXAoMSwgbnJvdyhkcml2ZTQpKSwgcmVwKDIsIG5yb3coZHJpdmU0KSksIHJlcCgzLCBucm93KGRyaXZlNCkpLCByZXAoNCwgbnJvdyhkcml2ZTQpKSkKbmFtZXMoZGZTZWcpIDwtIGMoIlNlZzEiLCAiU2VnMiIsICJTZWczIiwgIlNlZzQiKQoKY29tYmluZWREZl9TZWcxIDwtIGNiaW5kKGRyaXZlNCwgCiAgICAgICAgICAgICAgICAgICAgZHJpdmUxJE1lYW5QUF9TZWcwLCAKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkTWVhblBQX1NlZzEsIGRyaXZlMyRNZWFuUFBfU2VnMSwgCiAgICAgICAgICAgICAgICAgICAgZHJpdmUyJE1lYW5QUF9TZWcwLCBkcml2ZTMkTWVhblBQX1NlZzAsCiAgICAgICAgICAgICAgICAgICAgZHJpdmUyJFN0ZFBQLCBkcml2ZTMkU3RkUFAsCiAgICAgICAgICAgICAgICAgICAgZGZTZWckU2VnMQogICAgICAgICAgICAgICAgICApCmNvbWJpbmVkRGZfU2VnMiA8LSBjYmluZChkcml2ZTQsIAogICAgICAgICAgICAgICAgICAgIGRyaXZlMSRNZWFuUFBfU2VnMCwgCiAgICAgICAgICAgICAgICAgICAgZHJpdmUyJE1lYW5QUF9TZWcyLCBkcml2ZTMkTWVhblBQX1NlZzIsIAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRNZWFuUFBfU2VnMCwgZHJpdmUzJE1lYW5QUF9TZWcwLAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRTdGRQUCwgZHJpdmUzJFN0ZFBQLAogICAgICAgICAgICAgICAgICAgIGRmU2VnJFNlZzIKICAgICAgICAgICAgICAgICAgKQpjb21iaW5lZERmX1NlZzMgPC0gY2JpbmQoZHJpdmU0LCAKICAgICAgICAgICAgICAgICAgICBkcml2ZTEkTWVhblBQX1NlZzAsIAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRNZWFuUFBfU2VnMywgZHJpdmUzJE1lYW5QUF9TZWczLCAKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkTWVhblBQX1NlZzAsIGRyaXZlMyRNZWFuUFBfU2VnMCwKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkU3RkUFAsIGRyaXZlMyRTdGRQUCwKICAgICAgICAgICAgICAgICAgICBkZlNlZyRTZWczCiAgICAgICAgICAgICAgICAgICkKY29tYmluZWREZl9TZWc0IDwtIGNiaW5kKGRyaXZlNCwgCiAgICAgICAgICAgICAgICAgICAgZHJpdmUxJE1lYW5QUF9TZWcwLCAKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkTWVhblBQX1NlZzQsIGRyaXZlMyRNZWFuUFBfU2VnNCwgCiAgICAgICAgICAgICAgICAgICAgZHJpdmUyJE1lYW5QUF9TZWcwLCBkcml2ZTMkTWVhblBQX1NlZzAsCiAgICAgICAgICAgICAgICAgICAgZHJpdmUyJFN0ZFBQLCBkcml2ZTMkU3RkUFAsCiAgICAgICAgICAgICAgICAgICAgZGZTZWckU2VnNAogICAgICAgICAgICAgICAgICApCgpuYW1lcyhjb21iaW5lZERmX1NlZzEpIDwtIGMobmFtZXMoZHJpdmU0KSwgCiAgICAgICAgICAgICAgICAgICAgICAgIlBQX0Rldl8xX1R1cm5pbmciLAogICAgICAgICAgICAgICAgICAgICAgICJQUF9EZXZfMl9TdHJhaWdodCIsICJQUF9EZXZfM19TdHJhaWdodCIsIAogICAgICAgICAgICAgICAgICAgICAgICJQUF9EZXZfMl9UdXJuaW5nIiwgIlBQX0Rldl8zX1R1cm5pbmciLCAKICAgICAgICAgICAgICAgICAgICAgICAiU3RkX1BQXzIiLCAiU3RkX1BQXzMiLCAiU2VnbWVudCIpCm5hbWVzKGNvbWJpbmVkRGZfU2VnMikgPC0gYyhuYW1lcyhkcml2ZTQpLCAKICAgICAgICAgICAgICAgICAgICAgICAiUFBfRGV2XzFfVHVybmluZyIsCiAgICAgICAgICAgICAgICAgICAgICAgIlBQX0Rldl8yX1N0cmFpZ2h0IiwgIlBQX0Rldl8zX1N0cmFpZ2h0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgIlBQX0Rldl8yX1R1cm5pbmciLCAiUFBfRGV2XzNfVHVybmluZyIsIAogICAgICAgICAgICAgICAgICAgICAgICJTdGRfUFBfMiIsICJTdGRfUFBfMyIsICJTZWdtZW50IikKbmFtZXMoY29tYmluZWREZl9TZWczKSA8LSBjKG5hbWVzKGRyaXZlNCksIAogICAgICAgICAgICAgICAgICAgICAgICJQUF9EZXZfMV9UdXJuaW5nIiwKICAgICAgICAgICAgICAgICAgICAgICAiUFBfRGV2XzJfU3RyYWlnaHQiLCAiUFBfRGV2XzNfU3RyYWlnaHQiLCAKICAgICAgICAgICAgICAgICAgICAgICAiUFBfRGV2XzJfVHVybmluZyIsICJQUF9EZXZfM19UdXJuaW5nIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIlN0ZF9QUF8yIiwgIlN0ZF9QUF8zIiwgIlNlZ21lbnQiKQpuYW1lcyhjb21iaW5lZERmX1NlZzQpIDwtIGMobmFtZXMoZHJpdmU0KSwgCiAgICAgICAgICAgICAgICAgICAgICAgIlBQX0Rldl8xX1R1cm5pbmciLAogICAgICAgICAgICAgICAgICAgICAgICJQUF9EZXZfMl9TdHJhaWdodCIsICJQUF9EZXZfM19TdHJhaWdodCIsIAogICAgICAgICAgICAgICAgICAgICAgICJQUF9EZXZfMl9UdXJuaW5nIiwgIlBQX0Rldl8zX1R1cm5pbmciLCAKICAgICAgICAgICAgICAgICAgICAgICAiU3RkX1BQXzIiLCAiU3RkX1BQXzMiLCAiU2VnbWVudCIpCgpjb21iaW5lZERmX1NlZzEkU3ViamVjdCA8LSBwYXN0ZTAoYXMuZmFjdG9yKGNvbWJpbmVkRGZfU2VnMSRTdWJqZWN0KSwgIi5TMSIpCmNvbWJpbmVkRGZfU2VnMiRTdWJqZWN0IDwtIHBhc3RlMChhcy5mYWN0b3IoY29tYmluZWREZl9TZWcyJFN1YmplY3QpLCAiLlMyIikKY29tYmluZWREZl9TZWczJFN1YmplY3QgPC0gcGFzdGUwKGFzLmZhY3Rvcihjb21iaW5lZERmX1NlZzMkU3ViamVjdCksICIuUzMiKQpjb21iaW5lZERmX1NlZzQkU3ViamVjdCA8LSBwYXN0ZTAoYXMuZmFjdG9yKGNvbWJpbmVkRGZfU2VnNCRTdWJqZWN0KSwgIi5TNCIpCgpjb21iaW5lZERmIDwtIHJiaW5kKGNvbWJpbmVkRGZfU2VnMSwgY29tYmluZWREZl9TZWcyLCBjb21iaW5lZERmX1NlZzMsIGNvbWJpbmVkRGZfU2VnNCkKCmNvbWJpbmVkRGYkU3ViamVjdCA8LSBwYXN0ZTAoIiMiLCBzdHJfcGFkKGNvbWJpbmVkRGYkU3ViamVjdCwgMiwgcGFkPSIwIikpCmNvbWJpbmVkRGYkU2VnbWVudCA8LSBhcy5mYWN0b3IoY29tYmluZWREZiRTZWdtZW50KQpgYGAKCmBgYHtyfQpjb21iaW5lZERmX05vU3RyZXNzb3IgPC0gY29tYmluZWREZltjb21iaW5lZERmJEFjdGl2aXR5ID09ICJOTyIsXQpjb21iaW5lZERmX0NvZ25pdGl2ZSA8LSBjb21iaW5lZERmW2NvbWJpbmVkRGYkQWN0aXZpdHkgPT0gIkMiLF0KY29tYmluZWREZl9Nb3RvcmljIDwtIGNvbWJpbmVkRGZbY29tYmluZWREZiRBY3Rpdml0eSA9PSAiTSIsXQoKIyBjb21iaW5lZERmX05vU3RyZXNzb3IkU3ViamVjdCA8LSBhcy5mYWN0b3IoY29tYmluZWREZl9Ob1N0cmVzc29yJFN1YmplY3QpCiMgY29tYmluZWREZl9Db2duaXRpdmUkU3ViamVjdCA8LSBhcy5mYWN0b3IoY29tYmluZWREZl9Db2duaXRpdmUkU3ViamVjdCkKIyBjb21iaW5lZERmX01vdG9yaWMkU3ViamVjdCA8LSBhcy5mYWN0b3IoY29tYmluZWREZl9Nb3RvcmljJFN1YmplY3QpCmBgYAoKYGBge3J9CkNPTE9SX05PUk1BTCA8LSBsaXN0KGNvbG9yPSdyZ2IoMTIwLDEyMCwxMjApJykKQ09MT1JfQ09HTklUSVZFIDwtIGxpc3QoY29sb3I9J3JnYigxNTgsMjAyLDIyNSknKQpDT0xPUl9NT1RPUklDIDwtIGxpc3QoY29sb3I9J3JnYig1OCwyMDAsMjI1KScpCkNPTE9SX0ZBSUxVUkUgPC0gbGlzdChjb2xvcj0ncmVkJykKClRIUkVTSE9MRF9NSUxEID0gMC4wNwpUSFJFU0hPTERfRVhUUkVNRSA9IDAuMgoKTUFSS0VSX0xJTkVfTUlMRCA9IGxpc3QoY29sb3I9ImJsdWUiKQpNQVJLRVJfTElORV9FWFRSRU1FID0gbGlzdChjb2xvcj0icmVkIikKYGBgCgpgYGB7ciwgd2FybmluZz1GfQp5QXhpcyA8LSBsaXN0KHRpdGxlID0gJ1BlcmluYXNhbCBQZXJzcGlyYXRpb24gKExvZyknLCByYW5nZT1jKC0wLjMsIDAuNSkpCgpmaWdfTm9TdHJlc3NvciA8LSBwbG90X2x5KGNvbWJpbmVkRGZfTm9TdHJlc3NvciwgeCA9IH5TdWJqZWN0LCB5ID0gflBQX0Rldl8yX1N0cmFpZ2h0LCB0eXBlID0gJ2JhcicsIG5hbWUgPSAnQ29nbml0aXZlIC0gTWVhbiBQUCAoU3RyYWlnaHQpJywgbWFya2VyPUNPTE9SX0NPR05JVElWRSkgJT4lCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzNfU3RyYWlnaHQsIG5hbWUgPSAnTW90b3JpYyAtIE1lYW4gUFAgKFN0cmFpZ2h0KScsIG1hcmtlcj1DT0xPUl9NT1RPUklDKSAlPiUgCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzJfVHVybmluZywgbmFtZSA9ICdDb2duaXRpdmUgLSBNZWFuIFBQIChUdXJuaW5nKScsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkUpICU+JSAKICBhZGRfdHJhY2UoeSA9IH5QUF9EZXZfM19UdXJuaW5nLCBuYW1lID0gJ01vdG9yaWMgLSBNZWFuIFBQIChUdXJuaW5nKScsIG1hcmtlcj1DT0xPUl9NT1RPUklDKSAlPiUgCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2LCBuYW1lID0gJ0ZhaWx1cmUgLSBQUCBEZXZpYXRpb24nLCBtYXJrZXI9Q09MT1JfRkFJTFVSRSkgJT4lIAogIGFkZF9zZWdtZW50cyh4PSIjMS5TMSIsIHhlbmQ9IiM3LlM0IiwgeSA9IFRIUkVTSE9MRF9NSUxELCB5ZW5kID0gVEhSRVNIT0xEX01JTEQsIG5hbWU9IlRocmVzaG9sZDogTWlsZCBDaGFuZ2Ugb2YgUFAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoID0gJ2RvdCcpKSAlPiUKICAjIGFkZF9zZWdtZW50cyh4PSIjMDEiLCB4ZW5kPSIjNDEiLCB5ID0gVEhSRVNIT0xEX0VYVFJFTUUsIHllbmQgPSBUSFJFU0hPTERfRVhUUkVNRSwgbmFtZT0iVGhyZXNob2xkOiBFeHRyZW1lIENoYW5nZSBvZiBQUCIsCiAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZT1saXN0KGNvbG9yPSJkYXJrcmVkIiwgZGFzaCA9ICdkb3QnKSkgJT4lCiAgbGF5b3V0KHlheGlzID0geUF4aXMsIGJhcm1vZGUgPSAnZ3JvdXAnLCB0aXRsZT0iRmFpbHVyZSBEcml2aW5nIFxuIEdyb3VwPU5vIFN0cmVzc29yIikKCmh0bWx0b29sczo6dGFnTGlzdChmaWdfTm9TdHJlc3NvcikKYGBgCgpgYGB7ciwgd2FybmluZz1GfQp5QXhpcyA8LSBsaXN0KHRpdGxlID0gJ1BlcmluYXNhbCBQZXJzcGlyYXRpb24gKExvZyknLCByYW5nZT1jKC0wLjMsIDAuMykpCgpmaWdfQ29nbml0aXZlIDwtIHBsb3RfbHkoY29tYmluZWREZl9Db2duaXRpdmUsIHggPSB+U3ViamVjdCwgeSA9IH5QUF9EZXZfMl9TdHJhaWdodCwgdHlwZSA9ICdiYXInLCBuYW1lID0gJ0NvZ25pdGl2ZSAtIE1lYW4gUFAgKFN0cmFpZ2h0KScsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkUpICU+JQogIGFkZF90cmFjZSh5ID0gflBQX0Rldl8zX1N0cmFpZ2h0LCBuYW1lID0gJ01vdG9yaWMgLSBNZWFuIFBQIChTdHJhaWdodCknLCBtYXJrZXI9Q09MT1JfTU9UT1JJQykgJT4lIAogIGFkZF90cmFjZSh5ID0gflBQX0Rldl8yX1R1cm5pbmcsIG5hbWUgPSAnQ29nbml0aXZlIC0gTWVhbiBQUCAoVHVybmluZyknLCBtYXJrZXI9Q09MT1JfQ09HTklUSVZFKSAlPiUgCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzNfVHVybmluZywgbmFtZSA9ICdNb3RvcmljIC0gTWVhbiBQUCAoVHVybmluZyknLCBtYXJrZXI9Q09MT1JfTU9UT1JJQykgJT4lIAogIGFkZF90cmFjZSh5ID0gflBQX0RldiwgbmFtZSA9ICdGYWlsdXJlIC0gUFAgRGV2aWF0aW9uJywgbWFya2VyPUNPTE9SX0ZBSUxVUkUpICU+JSAKICBhZGRfc2VnbWVudHMoeD0iIzEyLlMxIiwgeGVuZD0iIzMuUzQiLCB5ID0gVEhSRVNIT0xEX01JTEQsIHllbmQgPSBUSFJFU0hPTERfTUlMRCwgbmFtZT0iVGhyZXNob2xkOiBNaWxkIENoYW5nZSBvZiBQUCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2ggPSAnZG90JykpICU+JQogICMgYWRkX3NlZ21lbnRzKHg9IiMwMiIsIHhlbmQ9IiMyMiIsIHkgPSBUSFJFU0hPTERfRVhUUkVNRSwgeWVuZCA9IFRIUkVTSE9MRF9FWFRSRU1FLCBuYW1lPSJUaHJlc2hvbGQ6IEV4dHJlbWUgQ2hhbmdlIG9mIFBQIiwKICAjICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lPWxpc3QoY29sb3I9ImRhcmtyZWQiLCBkYXNoID0gJ2RvdCcpKSAlPiUKICBsYXlvdXQoeWF4aXMgPSB5QXhpcywgYmFybW9kZSA9ICdncm91cCcsIHRpdGxlPSJGYWlsdXJlIERyaXZpbmcgXG4gR3JvdXA9Q29nbml0aXZlIikKCmh0bWx0b29sczo6dGFnTGlzdChmaWdfQ29nbml0aXZlKQpgYGAKCgoKYGBge3IsIHdhcm5pbmc9Rn0KeUF4aXMgPC0gbGlzdCh0aXRsZSA9ICdQZXJpbmFzYWwgUGVyc3BpcmF0aW9uIChMb2cpJywgcmFuZ2U9YygtMC4zLCAwLjUpKQoKZmlnX01vdG9yaWMgPC0gcGxvdF9seShjb21iaW5lZERmX01vdG9yaWMsIHggPSB+U3ViamVjdCwgeSA9IH5QUF9EZXZfMl9TdHJhaWdodCwgdHlwZSA9ICdiYXInLCBuYW1lID0gJ0NvZ25pdGl2ZSAtIE1lYW4gUFAgKFN0cmFpZ2h0KScsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkUpICU+JQogIGFkZF90cmFjZSh5ID0gflBQX0Rldl8zX1N0cmFpZ2h0LCBuYW1lID0gJ01vdG9yaWMgLSBNZWFuIFBQIChTdHJhaWdodCknLCBtYXJrZXI9Q09MT1JfTU9UT1JJQykgJT4lIAogIGFkZF90cmFjZSh5ID0gflBQX0Rldl8yX1R1cm5pbmcsIG5hbWUgPSAnQ29nbml0aXZlIC0gTWVhbiBQUCAoVHVybmluZyknLCBtYXJrZXI9Q09MT1JfQ09HTklUSVZFKSAlPiUgCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzNfVHVybmluZywgbmFtZSA9ICdNb3RvcmljIC0gTWVhbiBQUCAoVHVybmluZyknLCBtYXJrZXI9Q09MT1JfTU9UT1JJQykgJT4lIAogIGFkZF90cmFjZSh5ID0gflBQX0RldiwgbmFtZSA9ICdGYWlsdXJlIC0gUFAgRGV2aWF0aW9uJywgbWFya2VyPUNPTE9SX0ZBSUxVUkUpICU+JSAKICBhZGRfc2VnbWVudHMoeD0iIzI0LlMxIiwgeGVuZD0iIzkuUzQiLCB5ID0gVEhSRVNIT0xEX01JTEQsIHllbmQgPSBUSFJFU0hPTERfTUlMRCwgbmFtZT0iVGhyZXNob2xkOiBNaWxkIENoYW5nZSBvZiBQUCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2ggPSAnZG90JykpICU+JQogICMgYWRkX3NlZ21lbnRzKHg9IiMwNSIsIHhlbmQ9IiMzMSIsIHkgPSBUSFJFU0hPTERfRVhUUkVNRSwgeWVuZCA9IFRIUkVTSE9MRF9FWFRSRU1FLCBuYW1lPSJUaHJlc2hvbGQ6IEV4dHJlbWUgQ2hhbmdlIG9mIFBQIiwKICAjICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lPWxpc3QoY29sb3I9ImRhcmtyZWQiLCBkYXNoID0gJ2RvdCcpKSAlPiUKICBsYXlvdXQoeWF4aXMgPSB5QXhpcywgYmFybW9kZSA9ICdncm91cCcsIHRpdGxlPSJGYWlsdXJlIERyaXZpbmcgXG4gR3JvdXA6IE1vdG9yaWMiKQoKaHRtbHRvb2xzOjp0YWdMaXN0KGZpZ19Nb3RvcmljKQpgYGAKCgpgYGB7cn0KbGlicmFyeShubG1lKQpjb21iaW5lZERmJFN1YmplY3QgPSBhcy5mYWN0b3IoY29tYmluZWREZiRTdWJqZWN0KQpjb21iaW5lZERmJEFjdGl2aXR5ID0gYXMuZmFjdG9yKGNvbWJpbmVkRGYkQWN0aXZpdHkpCmNvbWJpbmVkRGYkUFBfRGV2X0dyb3VwID0gaWZlbHNlKGNvbWJpbmVkRGYkUFBfRGV2ID4gVEhSRVNIT0xEX01JTEQsIDEsIDApCmBgYAoKYGBge3J9Cm1vZGVsID0gbG1lKFBQX0RldiB+IAogICAgICAgICAgICAgIGFicyhQUF9EZXZfMl9TdHJhaWdodCkKICAgICAgICAgICAgICArIGFicyhQUF9EZXZfM19TdHJhaWdodCkKICAgICAgICAgICAgICArIGFicyhQUF9EZXZfMl9UdXJuaW5nKSAKICAgICAgICAgICAgICArIGFicyhQUF9EZXZfM19UdXJuaW5nKQogICAgICAgICAgICAgICsgZmFjdG9yKEFjdGl2aXR5KSwgCiAgICAgICAgICAgIHJhbmRvbT1+MXxTdWJqZWN0LAogICAgICAgICAgICBkYXRhPWNvbWJpbmVkRGYsCiAgICAgICAgICAgIG1ldGhvZD0iUkVNTCIpCgojIGFub3ZhKG1vZGVsKQpzdW1tYXJ5KG1vZGVsKQpwbG90KG1vZGVsKQpgYGAKCmBgYHtyfQptb2RlbCA9IGxtZShQUF9EZXYgfiAKICAgICAgICAgICAgICBhYnMoUFBfRGV2XzJfVHVybmluZykKICAgICAgICAgICAgICArIGZhY3RvcihBY3Rpdml0eSksIAogICAgICAgICAgICByYW5kb209fjF8U3ViamVjdCwKICAgICAgICAgICAgZGF0YT1jb21iaW5lZERmLAogICAgICAgICAgICBtZXRob2Q9IlJFTUwiKQoKIyBhbm92YShtb2RlbCkKc3VtbWFyeShtb2RlbCkKcGxvdChtb2RlbCkKYGBgCgpgYGB7cn0KbW9kZWwgPSBsbWUoUFBfRGV2IH4gCiAgICAgICAgICAgICAgUFBfRGV2XzJfU3RyYWlnaHQgKyAKICAgICAgICAgICAgICBQUF9EZXZfM19TdHJhaWdodCArIAogICAgICAgICAgICAgIFBQX0Rldl8xX1R1cm5pbmcgKyAKICAgICAgICAgICAgICBQUF9EZXZfMl9UdXJuaW5nICsgCiAgICAgICAgICAgICAgUFBfRGV2XzNfVHVybmluZyArIAogICAgICAgICAgICAgIFN0ZF9QUF8yICsgCiAgICAgICAgICAgICAgU3RkX1BQXzMgKwogICAgICAgICAgICAgIGZhY3RvcihBY3Rpdml0eSksIAogICAgICAgICAgICByYW5kb209fjF8U3ViamVjdCwKICAgICAgICAgICAgZGF0YT1jb21iaW5lZERmLAogICAgICAgICAgICBtZXRob2Q9IlJFTUwiKQoKIyBhbm92YShtb2RlbCkKc3VtbWFyeShtb2RlbCkKcGxvdChtb2RlbCkKYGBgCgojIyBNYWNoaW5lIExlYXJuaW5nCgpgYGB7cn0KY29tYmluZWREZiRQUF9EZXYgPC0gTlVMTAoKY29tYmluZWREZiRTdWJqZWN0IDwtIE5VTEwKY29tYmluZWREZiRBY3Rpdml0eV9OTyA8LSBpZmVsc2UoY29tYmluZWREZiRBY3Rpdml0eSA9PSAiTk8iLCAxLCAwKQpjb21iaW5lZERmJEFjdGl2aXR5X0MgPC0gaWZlbHNlKGNvbWJpbmVkRGYkQWN0aXZpdHkgPT0gIkMiLCAxLCAwKQpjb21iaW5lZERmJEFjdGl2aXR5X00gPC0gaWZlbHNlKGNvbWJpbmVkRGYkQWN0aXZpdHkgPT0gIk0iLCAxLCAwKQpjb21iaW5lZERmJEFjdGl2aXR5IDwtIE5VTEwKCmNvbWJpbmVkRGYkSW5TZWdtZW50MSA8LSBpZmVsc2UoY29tYmluZWREZiRTZWdtZW50ID09IDEsIDEsIDApCmNvbWJpbmVkRGYkSW5TZWdtZW50MiA8LSBpZmVsc2UoY29tYmluZWREZiRTZWdtZW50ID09IDIsIDEsIDApCmNvbWJpbmVkRGYkSW5TZWdtZW50MyA8LSBpZmVsc2UoY29tYmluZWREZiRTZWdtZW50ID09IDMsIDEsIDApCmNvbWJpbmVkRGYkSW5TZWdtZW50NCA8LSBpZmVsc2UoY29tYmluZWREZiRTZWdtZW50ID09IDQsIDEsIDApCmNvbWJpbmVkRGYkU2VnbWVudCA8LSBOVUxMCgpjb21iaW5lZERmJENsYXNzIDwtIGlmZWxzZShjb21iaW5lZERmJFBQX0Rldl9Hcm91cCA9PSAxLCBULCBGKQpjb21iaW5lZERmJFBQX0Rldl9Hcm91cCA8LSBOVUxMCmBgYAoKYGBge3J9CiMgbGlicmFyeShtZWZhKQojIGNvbWJpbmVkRGYgPC0gcmVwKGNvbWJpbmVkRGYsIDEwKSAKYGBgCgpgYGB7cn0Kbl9mb2xkcyA8LSAxMApwYXJhbXMgPC0gcGFyYW0gPC0gbGlzdChvYmplY3RpdmUgICA9ICJiaW5hcnk6bG9naXN0aWMiLCAKICAgICAgICAgICAgICAgYm9vc3RlciAgICAgICAgICA9ICJnYnRyZWUiLAogICAgICAgICAgICAgICBldmFsX21ldHJpYyAgICAgID0gImF1YyIsCiAgICAgICAgICAgICAgIGV0YSAgICAgICAgICAgICAgPSAwLjEsCiAgICAgICAgICAgICAgIG1heF9kZXB0aCAgICAgICAgPSA4LAogICAgICAgICAgICAgICBhbHBoYSAgICAgICAgICAgID0gMSwKICAgICAgICAgICAgICAgbGFtYmRhICAgICAgICAgICA9IDAsCiAgICAgICAgICAgICAgIGdhbW1hICAgICAgICAgICAgPSAwLjMsCiAgICAgICAgICAgICAgIG1pbl9jaGlsZF93ZWlnaHQgPSAwLjMsCiAgICAgICAgICAgICAgIHN1YnNhbXBsZSAgICAgICAgPSAxLAogICAgICAgICAgICAgICBjb2xzYW1wbGVfYnl0cmVlID0gMC41KQogICAgICAgICAgIAojIFhHQm9vc3QgTW9kZWwgICAgIAptbF9kYXRhIDwtIGFzLm1hdHJpeChjb21iaW5lZERmICU+JSBzZWxlY3QoLUNsYXNzKSkKCnhnYl9tIDwtIHhnYi5jdiggICBwYXJhbXMgICAgICAgICAgICAgICA9IHBhcmFtLAogICAgICAgICAgICAgICAgICBkYXRhID0gbWxfZGF0YSAsCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gIGNvbWJpbmVkRGYkQ2xhc3MsCiAgICAgICAgICAgICAgICAgIG5yb3VuZHMgICAgICAgICAgICAgPSA1MDAsCiAgICAgICAgICAgICAgICAgIHZlcmJvc2UgICAgICAgICAgICAgPSBGLAogICAgICAgICAgICAgICAgICBwcmVkaWN0aW9uICAgICAgICAgID0gVCwKICAgICAgICAgICAgICAgICAgbWF4aW1pemUgICAgICAgICAgICA9IFQsCiAgICAgICAgICAgICAgICAgIG5mb2xkICAgICAgICAgICAgICAgPSBuX2ZvbGRzLAogICAgICAgICAgICAgICAgICBtZXRyaWNzICAgICAgICAgICAgID0gYygiYXVjIiwgImVycm9yIiksCiAgICAgICAgICAgICAgICAgIGVhcmx5X3N0b3BwaW5nX3JvdW5kcyA9IDEwMCwKICAgICAgICAgICAgICAgICAgc2NhbGVfcG9zX3dlaWdodCAgICAgID0gMy4wNSkKCiMgeGdiX20kZXZhbHVhdGlvbl9sb2dbeGdiX20kYmVzdF9pdGVyYXRpb24sInRlc3RfYXVjX21lYW4iXQp4Z2JfbSRldmFsdWF0aW9uX2xvZ1t4Z2JfbSRiZXN0X2l0ZXJhdGlvbixdCgpgYGAKCmBgYHtyfQpsaWJyYXJ5KHBST0MpCgojIGl0ID0gd2hpY2gubWF4KHhnYl9tJGV2YWx1YXRpb25fbG9nJHRlc3RfYXVjX21lYW4pCiMgYmVzdC5pdGVyID0geGdiX20kZXZhbHVhdGlvbl9sb2ckaXRlcltpdF0KIyBiZXN0Lml0ZXIgCgpwbG90KHBST0M6OnJvYyhyZXNwb25zZSA9IGlmZWxzZShjb21iaW5lZERmJENsYXNzPT1ULCAxLCAwKSwKICAgICAgICAgICAgICAgcHJlZGljdG9yID0geGdiX20kcHJlZCwKICAgICAgICAgICAgICAgbGV2ZWxzPWMoMCwgMSkpLAogICAgIGx3ZD0xLjUpIApgYGAKCgoK